#include "App_Flank.h"

static int32_t App_Flank_ReadRelativePressure(FlankIndex_e flankIndex);

Flank flanksConfig[FLANK_MAXSIZE] = {
    /* 靠背侧翼 */
    [FLANK_INDEX_PASSIVE_LEFT] = { .airInflationValve =
                                       &solenoidValveList[SOLENOID_VALVE_INDEX_PASSIVE_LEFT_YTR6],
                                   .inflationEnable   = false,
                                   .airDeflateValve   = &solenoidValveList[SOLENOID_VALVE_INDEX_YTR1],
                                   .deflateEnable     = false,
                                   .fullPressureValue = FLANK_FULL_PRESSURE,
                                   .currentPressure   = 0,
                                   .flankIndex        = FLANK_INDEX_PASSIVE_LEFT,
                                   .flankType         = FLANK_TYPE_PASSIVE },

    /* 坐垫侧翼 */
    [FLANK_INDEX_PASSIVE_RIGHT] = { .airInflationValve =
                                        &solenoidValveList[SOLENOID_VALVE_INDEX_PASSIVE_RIGHT_YTR7],
                                    .inflationEnable   = false,
                                    .airDeflateValve   = &solenoidValveList[SOLENOID_VALVE_INDEX_YTR2],
                                    .deflateEnable     = false,
                                    .fullPressureValue = FLANK_FULL_PRESSURE,
                                    .currentPressure   = 0,
                                    .flankIndex        = FLANK_INDEX_PASSIVE_RIGHT,
                                    .flankType         = FLANK_TYPE_PASSIVE },
};

/**
 * @brief 初始化侧翼
 *
 */
void App_Flank_Init(void)
{
    /* 使能电磁阀 */
    Inf_SolenoidValve_Init();

    /* 初始化气泵 */
    Inf_Pump_Init();

    /* 初始化气压传感器 */
    Inf_CPS121_Init();
}

/**
 * @brief 启动侧翼, 开始充气
 *
 */
void App_Flank_Inflation(void)
{
    /* 开启电磁阀开关 和 气泵 */
    if (!solenoidValveSwitchIsOn) {
        Inf_SolenoidValve_EnableSwitch();
    }
    if (!pumpIsOn) {
        Inf_Pump_Enable();
    }

    /* 获取当前相对气压 */
    flanksConfig[FLANK_INDEX_PASSIVE_LEFT].currentPressure =
        App_Flank_ReadRelativePressure(FLANK_INDEX_PASSIVE_LEFT);
    flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].currentPressure =
        App_Flank_ReadRelativePressure(FLANK_INDEX_PASSIVE_RIGHT);

    LOG("Current Pressure Left: %d\n", flanksConfig[FLANK_INDEX_PASSIVE_LEFT].currentPressure);
    LOG("Current Pressure Right: %d\n", flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].currentPressure);

    /* 气压满时, 关闭电磁阀和气泵 */
    if (flanksConfig[FLANK_INDEX_PASSIVE_LEFT].currentPressure >=
            flanksConfig[FLANK_INDEX_PASSIVE_LEFT].fullPressureValue &&
        flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].currentPressure >=
            flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].fullPressureValue) {
        if (solenoidValveSwitchIsOn) {
            Inf_SolenoidValve_DisableSwitch();
        }
        if (pumpIsOn) {
            Inf_Pump_Disable();
        }
        LOG("Flank Inflation Finished! air full\n");
        return;
    }

    /* 充气使能 */
    if (flanksConfig[FLANK_INDEX_PASSIVE_LEFT].inflationEnable &&
        flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].inflationEnable) {

        uint8_t flankIndexList[] = { SOLENOID_VALVE_INDEX_PASSIVE_LEFT_YTR6,
                                     SOLENOID_VALVE_INDEX_PASSIVE_RIGHT_YTR7 };

        uint8_t flankIndexListSize = sizeof(flankIndexList) / sizeof(uint8_t);

        Inf_SolenoidValve_ActivateMultiValves(flankIndexList, flankIndexListSize);
    }
}

/**
 * @brief 关闭侧翼, 开始泄气
 *
 * @param flank 侧翼结构体指针
 */
void App_Flank_Deflate(void)
{
    /* 开启电磁阀 */
    if (!solenoidValveSwitchIsOn) {
        Inf_SolenoidValve_EnableSwitch();
    }

    /* 获取当前相对气压值 */
    flanksConfig[FLANK_INDEX_PASSIVE_LEFT].currentPressure =
        App_Flank_ReadRelativePressure(FLANK_INDEX_PASSIVE_LEFT);
    flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].currentPressure =
        App_Flank_ReadRelativePressure(FLANK_INDEX_PASSIVE_RIGHT);

    LOG("Current Pressure Left: %d\n", flanksConfig[FLANK_INDEX_PASSIVE_LEFT].currentPressure);
    LOG("Current Pressure Right: %d\n", flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].currentPressure);

    /* 泄气使能 */
    if (flanksConfig[FLANK_INDEX_PASSIVE_LEFT].deflateEnable &&
        flanksConfig[FLANK_INDEX_PASSIVE_RIGHT].deflateEnable) {

        uint8_t flankIndexList[] = { SOLENOID_VALVE_INDEX_YTR1, SOLENOID_VALVE_INDEX_YTR2 };

        uint8_t flankIndexListSize = sizeof(flankIndexList) / sizeof(uint8_t);

        Inf_SolenoidValve_ActivateMultiValves(flankIndexList, flankIndexListSize);
    }
}

/**
 * @brief 关闭所有侧翼阀门
 *
 */
void App_Flank_Stop(void)
{
    /* 关闭电磁阀 和 气泵 */
    if (solenoidValveSwitchIsOn) {
        Inf_SolenoidValve_DisableSwitch();
    }
    if (pumpIsOn) {
        Inf_Pump_Disable();
    }

    /* 关闭所有侧翼阀门 */
    for (uint8_t i = FLANK_INDEX_PASSIVE_LEFT; i < FLANK_INDEX_MAX; ++i) {
        flanksConfig[i].inflationEnable = false;
        flanksConfig[i].deflateEnable   = false;
    }

    uint8_t flankIndexList[]   = { SOLENOID_VALVE_INDEX_YTR1, SOLENOID_VALVE_INDEX_YTR2,
                                   SOLENOID_VALVE_INDEX_PASSIVE_LEFT_YTR6,
                                   SOLENOID_VALVE_INDEX_PASSIVE_RIGHT_YTR7 };
    uint8_t flankIndexListSize = sizeof(flankIndexList) / sizeof(uint8_t);
    Inf_SolenoidValve_DeactivateMultiValves(flankIndexList, flankIndexListSize);
}

// /**
//  * @brief 主动侧翼气压检测
//  *
//  */
// void App_Flank_ActiveFlankPressureMonitor(void)
// {
//     if (keyConfig.keyWorkMode == KEY_WORK_MODE_MASSAGE) {

//     }
// }

/**
 * @brief 读取指定气袋相对气压
 *
 * @return int32_t 相对气压值(单位: KPa)
 */
static int32_t App_Flank_ReadRelativePressure(FlankIndex_e flankIndex)
{
    if (flankIndex >= FLANK_INDEX_MAX) {
        LOG("FlankIndex error!\n");
        return 0;
    }

    /* 进入临界区, 保证I2C通讯正常 */
    taskENTER_CRITICAL();

    int32_t barometricPressure = Inf_CPS121_ReadCurrentPressure(AIR_PRESSURE_NUM_BAROMETRIC_PRESSURE);
    int32_t pressure           = 0;

    switch (flankIndex) {
    case FLANK_INDEX_ACTIVE_LEFT:
    case FLANK_INDEX_PASSIVE_LEFT: pressure = Inf_CPS121_ReadCurrentPressure(AIR_PRESSURE_NUM_LEFT); break;

    case FLANK_INDEX_ACTIVE_RIGHT:
    case FLANK_INDEX_PASSIVE_RIGHT:
        pressure = Inf_CPS121_ReadCurrentPressure(AIR_PRESSURE_NUM_RIGHT);
        break;
    }

    taskEXIT_CRITICAL();

    return pressure - barometricPressure;
}
